﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using Atom.NetFrame;
using Protocol.dto;
using Protocol;

namespace Atom.Logic.Fight
{
    public class FightRoom : AbsMulitHandle, HandleInterface
    {
        public ConcurrentDictionary<int, Role> Teams = new ConcurrentDictionary<int, Role>();
        public ConcurrentDictionary<int, List<InputCommand>> Frame2Inputs = new ConcurrentDictionary<int, List<InputCommand>>();

        private int m_Tick;
        private int m_SendTick;
        private bool m_IsRunning;
        private int m_MaxPlayerCount;
        private object m_LockObj = new object();
        private TimeManager m_TimeManager;
        private long m_GameStartTimestampMs = 0;
        private int m_TickSinceGameStart;
        public bool IsRunning { get { return m_IsRunning; } }
        public int Tick { get { return m_Tick; } set { m_Tick = value; } }


        public void ClientClose(UserToken ut, string error)
        {

        }

        public void ClientConnect(UserToken ut)
        {

        }

        public void MessageReceive(UserToken ut, SocketModel message)
        {
            switch (message.Command)
            {
                case FightProtocol.ENTER_GAMESCENE_REQ:
                    EnterGameScene(ut);
                    break;
                case FightProtocol.INPUT_REQ:
                    Input(ut, message);
                    break;
            }
        }
        /// <summary>
        /// 初始化
        /// </summary>
        public void Init(List<int> userList)
        {
            for (int i = 0; i < userList.Count; i++)
            {
                Role role = new Role();
                Teams.TryAdd(userList[i], role);
                UserToken ut = UserBiz.GetToken(userList[i]);
                Enter(ut);
            }
            m_MaxPlayerCount = userList.Count;
            //广播创建了房间
            ResCreateFightRoom res = new ResCreateFightRoom();
            res.Area = GetArea();
            res.RoldIds = userList;
            Broadcast(FightProtocol.CREATE_ROOM_RES, res.Encode());

            m_TimeManager = new TimeManager();


        }
        private int index = 0;
        /// <summary>
        /// 进入游戏
        /// </summary>
        public void EnterGameScene(UserToken ut)
        {
            if (index == 1)
            {
                Console.WriteLine("为什么还要进去");
                return;
            }

            Console.WriteLine("-------------------------------玩家进入游戏------------------------------");

            index++;
            int userID = UserBiz.GetUser(ut).ID;
            if (Teams.ContainsKey(userID))
            {
                Teams[userID].IsEnterGame = true;
            }
            bool isOk = true;
            foreach (var item in Teams)
            {
                if (!item.Value.IsEnterGame) isOk = false;
            }
            if (isOk)
            {
                //广播开始游戏
                Broadcast(FightProtocol.START_GAME_RES, null);
                Console.WriteLine("-----------------战斗开始-----------------------");
                m_IsRunning = true;
                m_TimeManager.Start();
                m_GameStartTimestampMs = m_TimeManager.RealTimeSinceStartUpMS;

            }
        }


        /// <summary>
        /// 输入
        /// </summary>
        private void Input(UserToken ut, SocketModel message)
        {
            lock (m_LockObj)
            {
                ReqPlayerInput input = ReqPlayerInput.Decode(message.Message);
                if (!Frame2Inputs.ContainsKey(input.LogicFrame))
                {
                    Frame2Inputs.TryAdd(input.LogicFrame, new List<InputCommand>());
                }
                if (Frame2Inputs[input.LogicFrame].Count >= m_MaxPlayerCount)
                {
                    Console.WriteLine("命令已经丢弃");
                    return;
                }
                //Console.WriteLine("本地帧：" + m_Tick + "命令类型" + input.InputCommand.CommandType);
                Frame2Inputs[input.LogicFrame].Add(input.InputCommand);
                if (CheckFullInput(false, input.LogicFrame))
                {
                    FrameLockLogic();
                }
            }


        }

        public void DoTick()
        {
            lock (m_LockObj)
            {
                if (IsRunning)
                {
                    m_TickSinceGameStart = (int)((m_TimeManager.RealTimeSinceStartUpMS - m_GameStartTimestampMs) / LockStepDefine.ServerDeltaTimeMS);
                    while (m_Tick <= m_TickSinceGameStart)
                    {
                        bool isOk = CheckFullInput(true, m_Tick);
                        if (isOk)
                        {
                            FrameLockLogic();
                        }
                        m_Tick++;
                    }

                }
            }
        }

        /// <summary>
        /// 帧逻辑
        /// </summary>
        public void FrameLockLogic()
        {
            if (!m_IsRunning) return;
            ResInputMessage res = new ResInputMessage();
            res.LogicFrame = m_SendTick;
            res.Cmds = Frame2Inputs[m_SendTick];
            Broadcast(FightProtocol.INPUT_RES, res.Encode());
            Console.WriteLine("本地帧：" + m_SendTick + "命令类型");
            m_SendTick++;
        }

        public bool CheckFullInput(bool isForce, int sendTick)
        {
            lock (m_LockObj)
            {
                //已经发过了
                if (sendTick < m_SendTick)
                {
                    return false;
                }
                if (!Frame2Inputs.ContainsKey(m_SendTick))
                {
                    if (!isForce)
                    {
                        return false;
                    }
                    else
                    {
                        List<InputCommand> cmds = new List<InputCommand>();
                        Frame2Inputs.TryAdd(sendTick, cmds);
                    }
                }
                int cmdCount = Frame2Inputs[sendTick].Count;
                if (!isForce)
                {
                    if (cmdCount < m_MaxPlayerCount) return false;
                }
                for (int i = 0; i < m_MaxPlayerCount; i++)
                {
                    if (i >= cmdCount)
                    {
                        InputCommand c = new InputCommand();
                        //c.CommandType = ECommandType.None;
                        Frame2Inputs[sendTick].Add(c);
                    }

                }
                return true;
            }

        }

        public bool LevelGame(int userID)
        {
            if (Teams.ContainsKey(userID))
            {
                Role r = null;
                Teams.TryRemove(userID, out r);
                if (Teams.Count <= 0)
                {

                    return true;
                }
            }
            else
            {
                Console.WriteLine("错误：角色不存在这个房间");
            }
            return false
;
        }

        public override byte Gettype()
        {
            return GameProtocol.TYPE_FIGHT;
        }
    }
}
